home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
PARSER
/
KPARS_00
/
KMATH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-09-02
|
15KB
|
564 lines
{$A-}
{$B-}
{$D-}
{$E-}
{$F+}
{$I-}
{$L-}
{$N-}
{$O+}
{$R-}
{$S-}
{$V-}
UNIT KMath;
{+H
---------------------------------------------------------------------------
Version - 0.21
File - KMath.PAS
Copyright (c) Klingon Software Services 1987..1993 except where noted.
All rights reserved.
Author - Keith S. Brown (except where otherwise noted)
Surface mail: Email:
K.Brown
2437 Bay Area Blvd #20
Houston, TX 77058 (USA) Voice:713-486-6765
Purpose - Standard Mathematics Functions and Procedures.
Remarks - None.
Language - Borland International's Turbo Pascal V:4.x+ for MS-DOS
Written - 1988.0202 V:0.00 (KSB) Wrote initial version.
Revised - 1988.1026 V:0.10 (KSB) Fixed ArcCos.
- 1990.0831 V:0.20 (KSB) Added Approx function
- 1990.0906 V:0.21 (KSB) Added Normalize procedure.
---------------------------------------------------------------------------}
INTERFACE
{}FUNCTION Approx(a,b:REAL):REAL;
{ Rounds b if Frac(b) > a; else truncs b
}
{}FUNCTION ArcCos(x:REAL):REAL;
{ Returns arcCosine of a value between -1 and 1
}
{}FUNCTION ArcSin(x:REAL):REAL;
{ Returns arcSine of a value between -1 and 1
}
{}FUNCTION ArcTan2(y,x:REAL):REAL;
{ Returns arcTangent of the ratio of x and y.
}
{}FUNCTION D_to_R(x:REAL):REAL;
{ Returns an angle converted to normalized radians (0 - 2π)
}
{}FUNCTION Exponent(x,n : REAL; VAR err:BYTE) : REAL;
{ raise x to the n'th power (with error checking)
}
{}FUNCTION Gate(x,cntr,wide:REAL):REAL;
{ Provides a rectangular pulse centered around CNTR of WIDE width.
}
{}FUNCTION Gaussian(x,cntr,variance:REAL):REAL;
{ provides a normal pulse centered around CNTR (mean) with VARIANCE.
}
{}FUNCTION Log2(x:REAL):REAL;
{ Returns Base 2 Log of x.
}
{}FUNCTION Log10(x:REAL):REAL;
{ Returns Base 10 Log of x.
}
{}PROCEDURE Normalize(value:REAL; VAR mantissa:REAL; VAR exponent:INTEGER);
{ compute the (1<mantissa<10) and exponent of value
}
{}FUNCTION OrderOf(v:REAL):INTEGER;
{ Returns the order of magnitude of v
}
{}FUNCTION PerCent_to_R(x:REAL):REAL;
{ Converts percent slope to radians
}
{}FUNCTION Power( x, n : REAL ) : REAL;
{ Returns X raised to the n'th power (no error checking)
}
{}FUNCTION R_to_D(x:REAL):REAL;
{ Returns an angle converted to normalized degrees (0 - 360)
}
{}FUNCTION R_to_PerCent(x:REAL):REAL;
{ Converts radians to percent slope
}
{}FUNCTION Sign( x:REAL ):REAL;
{ Returns the sign of x, ie., -1, +1, or 0
}
{}FUNCTION Sinc(x,hite,freq:REAL):REAL;
{ Sin(πƒx) / (πƒx)
}
{}FUNCTION Step(x:REAL):REAL;
{ unit step function
}
{}FUNCTION Tan(x:REAL):REAL;
{ Returns the Tangent of a value
}
{}FUNCTION Triangle(x,cntr,wide:REAL):REAL;
{ provide a triangular pulse centered at CNTR of WIDE width.
}
{====================================================================}
IMPLEMENTATION
CONST
epsilon: REAL = 1.0e-9;
{}FUNCTION ArcCos(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the ArcCosine of x.
Revised - 1988.0202 (KSB) Vers:0.00; Wrote it.
- 1988.1026 (KSB) Vers:0.10; Fixed for small values and for ±1.-
---------------------------------------------------------------------------}
VAR
t : REAL;
BEGIN
IF Abs(x) < epsilon THEN BEGIN { if x nearly zero }
ArcCos := Pi/2.0;
END ELSE
IF (1.0 + x) < epsilon THEN
{ if x = -1 }
ArcCos := Pi
ELSE
IF (x - 1.0) < epsilon THEN
{ if x = 1 }
ArcCos := 0.0
ELSE BEGIN { if x is anything else }
t := ArcTan(Sqrt(1.0-Sqr(x))/x);
IF t < 0.0 THEN
ArcCos := t + Pi
ELSE
ArcCos := t;
END {IF};
{}END {ArcCos};
{}FUNCTION ArcSin(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the ArcSin of x.
Revised - 1988.0202 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
IF (1.0 - Abs(x)) < 1.0e-9 THEN BEGIN
IF x < 0 THEN
ArcSin := -Pi/2.0
ELSE
ArcSin := Pi/2.0;
END ELSE
ArcSin := ArcTan(x/Sqrt(1.0-Sqr(x)));
{}END {ArcSin};
{}FUNCTION ArcTan2( y,x : REAL ) : REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the ArcTangent of x.
Revised - 1988.0202 (KSB) Wrote it.
---------------------------------------------------------------------------}
CONST
eps = 1.0e-4;
VAR
ix,iy: BYTE;
BEGIN
IF x < -eps THEN
ix := 255
ELSE
IF x > eps THEN
ix := 1
ELSE
ix := 0;
IF y < -eps THEN
iy := 255
ELSE
IF y > eps THEN
iy := 1
ELSE
iy := 0;
CASE ix OF
255 :
CASE iy OF
255 : ArcTan2 := Pi + ArcTan( Abs(y) / Abs(x) );
0 : ArcTan2 := Pi;
1 : ArcTan2 := Pi - ArcTan( Abs(y) / Abs(x) );
END {CASE};
0 :
CASE iy OF
255 : ArcTan2 := 3*Pi/2;
0 : ArcTan2 := 0;
1 : ArcTan2 := Pi/2;
END {CASE};
1 :
CASE iy OF
255 : ArcTan2 := 2*Pi - ArcTan( Abs(y) / Abs(x) );
0 : ArcTan2 := 0;
1 : ArcTan2 := ArcTan( Abs(y) / Abs(x) );
END {CASE};
END {CASE};
{}END {ArcTan2};
{}FUNCTION Log2(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the Base 2 Logrithm of x.
Revised - 1988.0202 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
Log2 := Ln(x)/Ln(2);
{}END {Log2};
{}FUNCTION Log10(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the Base 10 Logrithm of x.
Revised - 1988.0202 (KSB) Wrote it.
- 1988.0929 (KSB) Added low value trapping
---------------------------------------------------------------------------}
BEGIN
IF x < 1.0e-12 THEN
x := 1.0e-12;
Log10 := Ln(x)/Ln(10.0);
{}END {Log10};
{}FUNCTION Tan(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the Tangent of x.
Revised - 1988.0202 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
IF Abs(Cos(x)) < epsilon THEN
Tan := Pi/2
ELSE
Tan := Sin(x)/Cos(x);
{}END {Tan};
{}FUNCTION D_to_R( x : REAL ) : REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns an angle in radians.
Revised - 1988.0303 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
D_to_R := 2.0 * Pi * Frac(x / 360.0);
{}END {D_to_R};
{}FUNCTION R_to_D( x : REAL ) : REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns an angle in degrees.
Revised - 1988.0303 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
R_to_D := 360.0 * Frac(x / (2.0*Pi));
{}END {R_to_D};
{}FUNCTION PerCent_to_R(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns radians for an angle expressed as % slope.
Revised - 1988.0901 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
PerCent_to_R := ArcTan(x/100.0);
{}END {PerCent_to_R};
{}FUNCTION R_to_PerCent(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns % slope for an angle expressed as radians.
Revised - 1988.0901 (KSB) Wrote it.
---------------------------------------------------------------------------}
BEGIN
R_to_PerCent := Tan(x)*100.0;
{}END {R_to_PerCent};
{}FUNCTION Power( x, n : REAL ) : REAL;
{+H
---------------------------------------------------------------------------
Purpose - Raise X to the n'th power, Xⁿ (exponentiation).
---------------------------------------------------------------------------}
BEGIN
{Compute power using logarithms}
power := Exp( n * Ln( x ) );
{}END {Power};
{}FUNCTION OrderOf(v:REAL):INTEGER;
{+H
---------------------------------------------------------------------------
Purpose - Determines the order of magnitude of the argument
Revised - 1988.0708 (KSB) based on GetOrder.
---------------------------------------------------------------------------}
VAR
pwr : INTEGER;
BEGIN
v := Abs(v);
IF v = 0.0 THEN BEGIN
OrderOf := 0;
Exit;
END {IF};
pwr := 0;
WHILE v >= 10.0 DO BEGIN
v := v/10.0;
Inc(pwr);
END {WHILE};
WHILE (v < 1.0) DO BEGIN
v := v*10.0;
Dec(pwr);
END {WHILE};
OrderOf := pwr;
{}END {OrderOf};
{}FUNCTION Sign( x:REAL ):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns the sign of x, ie., -1, +1, or 0
---------------------------------------------------------------------------}
BEGIN
IF x < 0.0 THEN
Sign := -1.0
ELSE
IF x > 0.0 THEN
Sign := 1.0
ELSE
Sign := 0.0;
{}END {Sign};
{}FUNCTION Sinc(x,hite,freq:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Returns sinc(x)
---------------------------------------------------------------------------}
BEGIN
IF Abs(x) < epsilon THEN
Sinc := hite
ELSE
IF Abs(freq) < epsilon THEN
Sinc := 0.0
ELSE
Sinc := hite * Sin(Pi*x*freq) / (Pi*x*freq);
{}END {Sinc};
{}FUNCTION Step(x:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Provides unit step function
---------------------------------------------------------------------------}
BEGIN
IF x <= 0.0 THEN
Step := 0.0
ELSE
Step := 1.0;
{}END {Step};
{}FUNCTION Gate(x,cntr,wide:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - returns a rectangular pulse centered at CNTR of WIDE width.
---------------------------------------------------------------------------}
BEGIN
IF (x < (cntr-0.5*wide)) OR
(x > (cntr+0.5*wide)) THEN
Gate := 0.0
ELSE
Gate := 1.0;
{}END {Gate};
{}FUNCTION Triangle(x,cntr,wide:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - returns a triangular pulse centered at CNTR of WIDE width.
---------------------------------------------------------------------------}
BEGIN
IF (x < (cntr-wide)) OR
(x > (cntr+wide)) THEN
Triangle := 0.0
ELSE
IF Abs(wide) < epsilon THEN
Triangle := 1.0
ELSE
Triangle := (1.0 - Abs(x - cntr)/wide);
{}END {Triangle};
{}FUNCTION Gaussian(x,cntr,variance:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - returns a gaussian (normally distributed) pulse centered at
CNTR (mean) with VARIANCE.
---------------------------------------------------------------------------}
BEGIN
IF variance > epsilon THEN
Gaussian := Exp(-Sqr(x-cntr)/(2*Sqr(variance))) /
Sqrt( 2*Pi*variance )
ELSE
Gaussian := 1.0;
{}END {Gaussian};
{}FUNCTION Exponent(x,n : REAL; VAR err:BYTE) : REAL;
{+H
---------------------------------------------------------------------------
Purpose - Raise X to the n'th power, Xⁿ (exponentiation).
---------------------------------------------------------------------------}
CONST
epsilon = 0.000001;{tolerance to regard a number as an integer }
VAR
i : INTEGER;
p : REAL;
BEGIN
err := 0;
IF Abs(n - Round(n)) < epsilon THEN BEGIN { x raised to the n }
p := 1.0;
IF n > 0.0 THEN
FOR i := 1 TO Round(n) DO
p := p*x
ELSE
IF x = 0.0 THEN
p := 0
ELSE
FOR i := - 1 DOWNTO Round(n) DO
p := p/x;
Exponent := p;
END ELSE
IF x > 0.0 THEN BEGIN
p := n*Ln(x);
IF (p > 87) THEN
p := 87;
IF (p < - 87) THEN
p := - 87;
Exponent := Exp(p);
END ELSE
IF Abs(x) < epsilon THEN
Exponent := 0
ELSE
err := 1;
{}END {Exponent};
{}FUNCTION Approx(a,b:REAL):REAL;
{+H
---------------------------------------------------------------------------
Purpose - A is an approximation value, 0<A<1. B is the value-
to be adjusted. If the fractional part of B > A
then round B up to the nearest whole number, else
truncate B.
---------------------------------------------------------------------------}
BEGIN
IF (a>=1.0) OR (a<=0) THEN
Approx := Round(b)
ELSE BEGIN
IF Frac(b)>a THEN
Approx := Round(b)
ELSE
Approx := Trunc(b);
END {IF};
{}END {Approx};
{}PROCEDURE Normalize(value:REAL; VAR mantissa:REAL; VAR exponent:INTEGER);
{+H
---------------------------------------------------------------------------
Purpose - Given a real VALUE compute its (1 < MANTISSA < 10) & EXPONENT-
---------------------------------------------------------------------------}
BEGIN
exponent := 0;
mantissa := value;
REPEAT
IF (mantissa >= 10.0) THEN BEGIN
mantissa := mantissa / 10.0;
Inc(exponent);
END ELSE
IF (mantissa < 1.0) THEN BEGIN
mantissa := mantissa * 10.0;
Dec(exponent);
END {IF};
UNTIL (mantissa >= 1.0) AND (mantissa < 10.0);
{}END {Normalize};
END {UNIT}.